package com.nulldev.util.os.winepint;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import com.nulldev.util.io.FileUtil;
import com.nulldev.util.java.ProcessUtil;
import com.nulldev.util.java.swing.extSwing.eActiveConsoledBar;
import com.nulldev.util.java.swing.extSwing.eAdvancedMessage;
import com.nulldev.util.java.swing.extSwing.resources.eMessageType;
import com.nulldev.util.os.OSUtil;
import com.nulldev.util.threading.ArgumentedRunnable;
import com.nulldev.util.threading.legacy.ThreadExecutor;
import com.nulldev.util.uri.URIUtil;
import com.nulldev.util.uri.nget.nGet;
import com.nulldev.util.uri.nget.nGetEvent;

public class wTricks {

	private static void checkWine() {
		if (!WineDetector.isWinePresent()) {
			throw new RuntimeException("Invalid call! Wine is not present.");
		}
	}
	
	private static boolean checkWineB() {
		if (!WineDetector.isWinePresent()) {
			return false;
		}
		return true;
	}
	
	private static boolean cabExtractExists() {
		return OSUtil.PackageUtil.isPackage("cabextract");
	}
	
	public static enum Module {
		
		DirectX9(Tasks.INSTALL_DIRECTX9)
		;
		
		private final ArgumentedRunnable run;
		private Module(final ArgumentedRunnable run) {
			this.run = run;
		}
		
		public void run(final String[] args) {
			this.run.run(args);
		}

	}
	
	private static class Tasks {
		private static final ArgumentedRunnable INSTALL_DIRECTX9 = new ArgumentedRunnable() {
			
			public static final String DIRECTX_URL = "https://download.microsoft.com/download/E/E/1/EE17FF74-6C45-4575-9CF4-7FC2597ACD18/directx_feb2010_redist.exe";
			
			@Override
			public void run(String[] args) {
				if (!checkWineB()) {
					final eAdvancedMessage evm = eAdvancedMessage.main(eMessageType.ERROR);
					evm.setTitle("wTricks: Fatal Error!");
					evm.setMessageTitle("Wine is missing.");
					evm.setMessage("We couldn't find Wine.");
					evm.waitForOK();
					return;
				}
				final eActiveConsoledBar ecv = eActiveConsoledBar.main();
				ecv.setTitle("wTricks: Installing DirectX 9");
				ecv.setIndeterminate(true);
				if (!FileUtil.safeCreate(FileUtil.tempDir().toString() + "/_wTricks_directx9_feb2010_redist.exe").exists()) {
					ecv.setText("Downloading DirectX...");
					ecv.appendConsole("Running nGet for DirectX9...");
					final nGet ng = new nGet(URIUtil.safeCreate(DIRECTX_URL));
					ng.registerEvent(new nGetEvent() {
						
						String pre = "";
						
						@Override
						public void onStart(long length) {
							ecv.appendConsole("Preparing to download DirectX. [File Size: " + FileUtil.convertToStringRepresentation(length) + "]");
							pre = ecv.getTextPane().getText();
						}
						
						@Override
						public void onFinish() {
							ecv.appendConsole("nGet: Downloaded DirectX.");
							pre = ecv.getTextPane().getText();
						}
						
						@Override
						public void onError() {
							ecv.appendConsole("<!> Error occured!");
							pre = ecv.getTextPane().getText();
						}
						
						@Override
						public void onDownload(long bytes, double percent) {
							ecv.setConsoleText(pre);
							ecv.appendConsole("Downloading..." + FileUtil.convertToStringRepresentation(bytes));
						}
					});
					ng.overrideName("_wTricks_directx9_feb2010_redist.exe");
					ThreadExecutor.execute(new Runnable() {
						
						@Override
						public void run() {
							ng.download();
							ng.waitTillFinished();
							ecv.appendConsole("DirectX downloaded.");
							ecv.setText("Installing DirectX...");
							phase2(ecv, args);
						}
					});
				}else {
					ecv.setText("Installing DirectX...");
					this.phase2(ecv, args);
				}
			}
			
			public void phase2(final eActiveConsoledBar ecv, final String[] args) {
				ecv.setText("Extracting...");
				if (!cabExtractExists()) {
					ecv.end();
					final eAdvancedMessage evm = eAdvancedMessage.main(eMessageType.ERROR);
					evm.setTitle("wTricks: Fatal Error!");
					evm.setMessageTitle("Extraction failed!");
					evm.setMessage("cabextract is missing! Halting.");
					evm.waitForOK();
					return;
				}
				ecv.setText("Running cabextract...");
				if (!FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010").isDirectory()) {
					ecv.appendConsole("Creating directory...");
					FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010").mkdirs();
				}
				final String cmd0 = "cabextract -d /tmp/_wTricks/_directx9_feb2010 /tmp/_wTricks_directx9_feb2010_redist.exe";
				ecv.appendConsole(cmd0);
				try {
					ecv.appendConsole(ProcessUtil.execCmd(cmd0));
				} catch (IOException e) {
					ecv.end();
					final eAdvancedMessage evm = eAdvancedMessage.main(eMessageType.ERROR);
					evm.setTitle("wTricks: Fatal Error!");
					evm.setMessageTitle("Extraction failed!");
					evm.setMessage("Error occured during execution.");
					evm.waitForOK();
					return;
				}
				if (FileUtil.listFilesForFolder(FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010")).size() == 0) {
					ecv.end();
					final eAdvancedMessage evm = eAdvancedMessage.main(eMessageType.ERROR);
					evm.setTitle("wTricks: Fatal Error!");
					evm.setMessageTitle("Extraction failed!");
					evm.setMessage("No files were extracted.");
					evm.waitForOK();
					return;
				}
				ecv.appendConsole("Files extracted!");
				ecv.setText("Extracting dlls...");
				ecv.appendConsole("Extracting dlls...");
				if (!FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010/dlls").isDirectory()) {
					FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010/dlls").mkdirs();
				}
				for (final File f : FileUtil.listFilesForFolder(FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010"))) {
					final String ext = FileUtil.getFileExtension(f);
					if (ext.equals("cab") || ext.equals(".cab")) {
						try {
							ProcessUtil.execCmd(ecv.appendConsoleB("cabextract -d /tmp/_wTricks/_directx9_feb2010/dlls " + f.getAbsolutePath()));
						} catch (IOException e) {
							ecv.end();
							final eAdvancedMessage evm = eAdvancedMessage.main(eMessageType.ERROR);
							evm.setTitle("wTricks: Fatal Error!");
							evm.setMessageTitle("DLL Extraction failed!");
							evm.setMessage("Something went wrong.");
							evm.waitForOK();
							System.exit(-1);
							break;
						}
					}
				}
				ecv.setText("Installing dlls...");
				ecv.appendConsole("Installing dlls...");
				final String pre00 = ecv.getTextPane().getText();
				ecv.appendConsole("Getting dlls...");
				ecv.setConsoleText(pre00);
				final ArrayList<File> dlls = FileUtil.listFilesForFolderExt(FileUtil.safeCreate("/tmp/_wTricks/_directx9_feb2010/dlls"), "dll");
				ecv.appendConsole("Getting dlls... " + dlls.size() + " found");
				ecv.setText("Registering dlls...");
				ecv.appendConsole("Loading dlls to Wine...");
				ecv.end();
				final eAdvancedMessage evm = eAdvancedMessage.main(eMessageType.ERROR);
				evm.setTitle("wTricks: Fatal Error!");
				evm.setMessageTitle("DLL Installation failed!");
				evm.setMessage("function() --> Unimplemented!");
				evm.waitForOK();
				return;
			}
		};
	}
}
